home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / kcl / akcl / akcl1615.lha / lsp / sloop.lsp < prev    next >
Lisp/Scheme  |  1991-12-10  |  42KB  |  1,231 lines

  1. ;;; -*- Mode:LISP; Package:(SLOOP LISP);Syntax:COMMON-LISP;Base:10 -*- ;;;;;
  2. ;;;                                                                    ;;;;;
  3. ;;;     Copyright (c) 1985,86 by William Schelter,                     ;;;;;
  4. ;;;     All rights reserved                                            ;;;;;
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6.  
  7.  
  8. ;;; Report bugs to wfs@carl.ma.utexas.edu
  9. ;;; It comes with ABSOLUTELY NO WARRANTY but we hope it is useful.
  10.  
  11.  
  12. ;;; The following code is meant to run in COMMON LISP and to provide
  13. ;;; extensive iteration facilities, with very high backwards compatibility
  14. ;;; with the traditional loop macro. It is meant to be publicly available!
  15. ;;; Anyone is hereby given permission to copy it provided he does not make
  16. ;;; ANY changes to the file unless he is William Schelter.  He may change
  17. ;;; the behavior after loading it by resetting the global variables such
  18. ;;; as like *Use-locatives*, *automatic-declarations*,..  listed at the
  19. ;;; beginning of this file.
  20.  
  21. ;;; The original of this file is on
  22. ;;; rascal.ics.utexas.edu:/usr2/ftp/pub/sloop.lisp.   I am happy to accept
  23. ;;; suggestions for different defaults for various implementations, or for
  24. ;;; improvements.
  25.  
  26.  
  27. ;;If you want to redefine the common lisp loop you may include in your code:
  28. ;;; (defmacro loop (&body body) (parse-loop body))
  29.  
  30. ;;         Principal New Features
  31.  
  32. ;;; Sloop is extremely user extensible so that you may easily redefine
  33. ;;; most behavior, or add additional collections, and paths.  There are a
  34. ;;; number of such examples defined in this file, including such
  35. ;;; constructs as
  36.  
  37. ;;; .. FOR v IN-FRINGE x ..         (iterate through the fringe of a tree x)
  38. ;;; .. SUM v ..                     (add the v)
  39. ;;; .. AVERAGING v ..      
  40. ;;; .. FOR sym IN-PACKAGE y         (iterate through symbols in a package y)
  41. ;;; .. COLLATE v ..                 (for collecting X into an ordered list),
  42. ;;; .. FOR (elt i) IN-ARRAY ar      (iterate through array ar, with index i)
  43. ;;; .. FOR (key elt) IN-TABLE foo.. (if foo is a hash table)
  44.  
  45. ;;; you can combine any collection method with any path.
  46. ;;; Also there is iteration over products so that you may write
  47. ;;; (SLOOP FOR i BELOW k
  48. ;;;       SLOOP (FOR j BELOW i
  49. ;;;                  COLLECTING (foo i j)))
  50.  
  51. ;;; Declare is fully supported.  The syntax would be
  52. ;;; (sloop for u in l with v = 0
  53. ;;;       declare (fixnum u v)
  54. ;;;       do ....
  55.  
  56. ;;; This extensibility is gained by the ability to define a "loop-macro",
  57. ;;; which plays a role analagous to an ordiary lisp macro.  See eg.
  58. ;;; definitions near that of "averaging".  Essentially a "loop-macro"
  59. ;;; takes some arguments (supplied from the body of the loop following its
  60. ;;; occurrence, and returns a new form to be stuffed onto the front of the
  61. ;;; loop form, in place of it and its arguments).
  62.  
  63. ;;; Compile notes: For dec-20 clisp load the lisp file before compiling.
  64.  
  65.  
  66. ;;; there seems to be no unanimity about what in-package etc. does on
  67. ;;; loading and compiling a file.  The following is as close to the
  68. ;;; examples in the Common Lisp manual, as we could make it.  The user
  69. ;;; should put (require "SLOOP") and then (use-package "SLOOP") early in
  70. ;;; his init file.  Note use of the string to avoid interning 'sloop in
  71. ;;; some other package.
  72.  
  73.  
  74. (in-package "SLOOP"  :use '(LISP))  
  75. (eval-when (compile eval load)
  76.  
  77. (export '(loop-return sloop def-loop-collect def-loop-map
  78.               def-loop-for def-loop-macro local-finish
  79.               loop-finish) (find-package "SLOOP"))
  80.  
  81. )
  82.  
  83. ;;; some variables that may be changed to suit different implementations:
  84.  
  85. (eval-when (compile load eval)
  86.  
  87. (defvar *use-locatives* nil "See sloop.lisp")   ;#+lispm t #-lispm nil 
  88. ;;; If t should have locf, such that if we do
  89. ;;;   (setf b nil) (setq a (locf b))
  90. ;;;    then the command
  91. ;;;   (setf (cdr a) (cons 3 nil)) means that b==>(3).
  92. ;;; This is useful for building lists starting with a variable pointing to
  93. ;;; nil, since otherwise we must check each time if the list has really
  94. ;;; been started, before we do a (setf (cdr b) ..)
  95.  
  96. (defvar *Automatic-declarations*  #+lispm nil  #-lispm
  97.   '(:from fixnum) "See sloop.lisp")
  98.  
  99. ;;; some other reasonable ones would be :count fixnum :max fixnum
  100. ;;; Automatic declarations for variables in the stepping and collecting,
  101. ;;; so for i below n, gives i and n a :from declaration (here fixnum)
  102.  
  103.  
  104. ;;valid keys in *automatic-declarations*
  105. (defvar *auto-type* '(:from :in :collect))
  106. ;;give automatic register declaration to these variables 
  107. (defvar *auto-register* '(:from :in :collect))
  108. (eval-when (compile eval load)
  109. (proclaim '(declaration :register))
  110. )
  111.  
  112.  
  113. (defvar *type-check* t "If t adds a type check on bounds of from loop
  114. if there is and automatic declare")
  115.  
  116. (defvar *macroexpand-hook-for-no-copy* #-(or lmi ti) 'funcall #+(or lmi ti) t)
  117. ;;; some lisps remember a macro so that (loop-return) will expand eq forms
  118. ;;; always in the same manner, even if the form is in a macrolet! To
  119. ;;; defeat this feature we copy all macro expansions unless
  120. ;;; *macro-expand-hook* = *macroexpand-hook-for-no-copy*
  121. )
  122.  
  123.  
  124. ;;; *****ONLY CONDITIONALIZATIONS BELOW HERE SHOULD BE FOR BUG FIXES******
  125. ;;; eg. some kcls don't return nil from a prog by default!
  126.  
  127. ;;; all macros here in here.
  128. (eval-when (compile eval load)
  129.  
  130. (defparameter *sloop-translations* '((appending . append)
  131.              ((collecting collect) . collect)
  132.              ((maximizing maximize) . maximize)
  133.              ((minimizing minimize) . minimize)
  134.              (nconcing . nconc)
  135.              ((count counting) . count)
  136.              (summing . sum)
  137.              (if . when)
  138.              (as . for)
  139.              (in-fringe . in-fringe)
  140.              (collate . collate)
  141.              (in-table . in-table)
  142.              (in-carefully . in-carefully)
  143.              (averaging . averaging)
  144.              (repeat . repeat)
  145.              (first-use . first-use)
  146.              (in-array . in-array))
  147.   "A list of cons's where the translation is the cdr, and the car
  148. is a list of names or name to be translated.  Essentially allows 'globalizing'
  149. a symbol for the purposes of being a keyword in a sloop")
  150.  
  151.  
  152. (defparameter *additional-collections* nil)
  153.  
  154. (defmacro lcase (item &body body)
  155.   (let (bod last-case tem)
  156.     (do ((rest body (cdr rest)) (v))
  157.     ((or last-case (null rest)))
  158.       (setq  v (car rest))
  159.       (push
  160.     (cond ((eql (car v) t) (setq last-case t) v)
  161.           ((eql (car v) :collect)
  162.            `((loop-collect-keyword-p .item.) ,@ (cdr v)))
  163.           ((eql (car v) :no-body)
  164.            `((parse-no-body  .item.) ,@ (cdr v)))
  165.           ((setq tem
  166.              (member (car v) '(:sloop-macro :sloop-for :sloop-map)))
  167.            `((and (symbolp .item.)(get .item. ,(car tem))) ,@ (cdr v)))
  168.           (t
  169.            `((l-equal .item. ',(car v)) ,@ (cdr v))))
  170.     bod))
  171.     (or last-case (push `(t (error "lcase fell off end ~a  " .item.)) bod))
  172.     `(let ((.item. (translate-name ,item)))
  173.        (cond ,@ (nreverse bod)))))
  174.  
  175. (defun desetq1 (form val)
  176.   (cond ((symbolp form)
  177.      (and form `(setf ,form ,val)))
  178.     ((consp form)
  179.      `(progn ,(desetq1 (car form) `(car ,val))
  180.          ,@ (if (consp (cdr form))
  181.             (list(desetq1 (cdr form) `(cdr ,val)))
  182.               (and (cdr form) `((setf ,(cdr form) (cdr ,val)))))))
  183.     (t (error ""))))
  184.  
  185. (defmacro desetq (form val)
  186.   (cond ((atom val) (desetq1 form val))
  187.     (t (let ((value (gensym)))
  188.          `(let ((,value ,val)) , (desetq1 form value))))))
  189.  
  190. (defmacro loop-return (&rest vals)
  191.   (cond ((<=  (length vals) 1)
  192.      `(return ,@ vals))
  193.     (t`(return (values  ,@ vals)))))
  194.  
  195. (defmacro loop-finish ()
  196.   `(go finish-loop))
  197.  
  198. (defmacro local-finish ()
  199.   `(go finish-loop))
  200.  
  201. (defmacro sloop (&body body)
  202.   (parse-loop body))
  203.   
  204. (defmacro def-loop-map (name args &body body)
  205.   (def-loop-internal name args body 'map))
  206. (defmacro def-loop-for (name args &body body )
  207.   (def-loop-internal name args body 'for nil 1))
  208. (defmacro def-loop-macro (name args &body body)
  209.   (def-loop-internal name args body 'macro))
  210. (defmacro def-loop-collect (name arglist &body body )
  211.        "Define function of 2 args arglist= (collect-var value-to-collect)"
  212.   (def-loop-internal name arglist body 'collect '*additional-collections* 2 2))
  213.  
  214. (defmacro sloop-swap ()
  215.  `(progn (rotatef a *loop-bindings*)
  216.   (rotatef b  *loop-prologue*)
  217.   (rotatef c *loop-epilogue*)
  218.   (rotatef e *loop-end-test*)
  219.   (rotatef f *loop-increment*)
  220.   (setf *inner-sloop* (not *inner-sloop*))
  221.   ))
  222.  
  223. ) ;;end of macros
  224.  
  225. (defun l-equal (a b)
  226.   (and (symbolp a)
  227.        (cond ((symbolp b)
  228.           (equal (symbol-name a) (symbol-name b)))
  229.          ((listp b)
  230.           (member  a b :test 'l-equal)))))
  231.  
  232. (defun loop-collect-keyword-p (command)
  233.   (or (member command '(collect append nconc sum count) :test 'l-equal)
  234.       (find command *additional-collections* :test 'l-equal)))
  235.               
  236. (defun translate-name (name)
  237.   (cond ((and (symbolp name)
  238.           (cdar (member name *sloop-translations*
  239.                 :test 'l-equal :key 'car))))
  240.     (t name)))
  241.  
  242. (defun loop-pop ()
  243.   (declare (special *last-val* *loop-form*))
  244.   (cond (*loop-form*
  245.           (setq *last-val* (pop *loop-form*)))
  246.     (t (setq *last-val* 'empty-form) nil)))
  247.  
  248. (defun loop-un-pop ()  (declare (special *last-val* *loop-form*))
  249.   (case *last-val*
  250.     (empty-form nil)
  251.     (already-un-popped (error "you are un-popping without popping"))
  252.     (t  (push *last-val* *loop-form*)
  253.         (setf *last-val* 'alread-un-popped))))
  254.  
  255. (defun loop-peek () (declare (special *last-val* *loop-form*))
  256.    (car *loop-form*))
  257.  
  258. (defun loop-let-bindings(binds)
  259.   (do ((v (car binds) (cdr v)))
  260.       ((null v) (nreverse (car binds)))
  261.       (or (cdar v) (setf (car v) (caar v)))))
  262.  
  263. (defun parse-loop (form &aux inner-body)
  264.   (let ((*loop-form* form)
  265.     (*Automatic-declarations* *Automatic-declarations*)
  266.     *last-val* *loop-map* 
  267.     *loop-body* 
  268.     *loop-name*
  269.     *loop-prologue* *inner-sloop*
  270.     *loop-epilogue* *loop-increment*
  271.     *loop-collect-pointers*  *loop-map-declares*
  272.     *loop-collect-var*     *no-declare*
  273.     *loop-end-test*
  274.     *loop-bindings*
  275.     *product-for*
  276.     *type-test-limit*
  277.     local-macros
  278.     (finish-loop 'finish-loop)
  279.     )
  280.     (declare (special *loop-form* *last-val* *loop-map* 
  281.               *loop-collect-pointers*
  282.               *loop-name* *inner-sloop*
  283.               *loop-body*
  284.               *loop-prologue* 
  285.               *no-declare*
  286.               *loop-bindings*
  287.               *loop-collect-var*  *loop-map-declares*
  288.               *loop-epilogue* *loop-increment*
  289.               *loop-end-test* *product-for*
  290.               *type-test-limit*
  291.               ))
  292.     (unless (and (symbolp (car *loop-form*))  (car *loop-form*))
  293.         (push 'do  *loop-form*))    ;compatible with common lisp loop..
  294.     (parse-loop1)
  295.     (when (or *loop-map* *product-for*)
  296.       (or *loop-name* (setf *loop-name* (gensym "SLOOP")))
  297.       (and (eql 'finish-loop finish-loop)
  298.            (setf finish-loop (gensym "FINISH"))))
  299. ;;; some one might use local-finish,local-return or loop-finish, so they might
  300. ;;; be bound at an outer level.  WE have to always include this since
  301. ;;; loop-return may be being bound outside.
  302.     (and                ; *loop-name*
  303.       (push 
  304.     `(loop-return (&rest vals)
  305.               `(return-from ,',*loop-name* (values ,@ vals)))
  306.     local-macros))
  307.     (when  t;; (or (> *loop-level* 1) (not (eql finish-loop 'finish-loop)))
  308.        (push      `(loop-finish () `(go ,',finish-loop)) local-macros)
  309.        (push      `(local-finish () `(go ,',finish-loop)) local-macros))
  310.     (and *loop-collect-var*
  311.      (push   `(return-from ,*loop-name* , *loop-collect-var*)
  312.          *loop-epilogue*))
  313.     (setq inner-body (append  *loop-end-test*
  314.                   (nreverse *loop-body*)
  315.                   (nreverse    *loop-increment*)))
  316.     (cond (*loop-map*
  317.         (setq inner-body (substitute-sloop-body inner-body)))
  318.       (t (setf inner-body (cons 'next-loop
  319.                     (append inner-body '((go next-loop)))))))
  320.     (let ((bod 
  321.         `(macrolet ,local-macros
  322.                (block ,*loop-name*
  323.                   (tagbody
  324.                 ,@ (append
  325.                      (nreverse *loop-prologue*)
  326.                      inner-body
  327.                      `(,finish-loop)
  328.                      (nreverse *loop-epilogue*)
  329.                      #+kcl '((loop-return  nil))))))
  330.         
  331.         ))
  332. ;;; temp-fix..should not be necessary but some lisps cache macro
  333. ;;; expansions.  and ignore the macrolet!!
  334.       (unless  (eql *macroexpand-hook* *macroexpand-hook-for-no-copy*)
  335.            (setf bod (copy-tree bod)))
  336.       (dolist (v *loop-bindings*)
  337.           (setf bod
  338.             `(let ,(loop-let-bindings v)
  339.                ,@(and (cdr v) `(,(cons 'declare (cdr v))))
  340.                ,bod)))
  341.       bod
  342.       ))) 
  343.  
  344. (defun parse-loop1 ()
  345.   (declare (special *loop-form*
  346.             *loop-body* *loop-increment*
  347.             *no-declare* *loop-end-test*
  348.             *loop-name* ))
  349.   (lcase (loop-peek)
  350.      (named (loop-pop) (setq *loop-name* (loop-pop)))
  351.      (t nil))
  352.   (do ((v (loop-pop) (loop-pop)))
  353.       ((and (null v) (null *loop-form*)))
  354.       (lcase v
  355.          (:no-body)
  356.          (for (parse-loop-for))
  357.          (while (push
  358.               `(or ,(loop-pop) (local-finish))  *loop-body*))
  359.          (until (push
  360.               `(and ,(loop-pop) (local-finish))  *loop-body*))
  361.          (do (setq *loop-body* (append (parse-loop-do) *loop-body*)))
  362.          ((when unless) (setq *loop-body*
  363.                   (append (parse-loop-when) *loop-body*)))
  364.          (:collect  (setq *loop-body*
  365.                   (append (parse-loop-collect) *loop-body*)))
  366.          )))
  367.  
  368.  
  369. (defun parse-no-body (com &aux (found t) (first t))
  370.   "Reads successive no-body-contribution type forms, like declare,
  371. initially, etc.  which can occur anywhere. Returns t if it finds some
  372. otherwise nil"
  373.   (declare (special *loop-form*
  374.             *loop-body*
  375.             *loop-increment*
  376.             *no-declare* *loop-end-test*
  377.             *loop-name* ))
  378.   (do ((v com (loop-pop)))
  379.       ((null (or first *loop-form*)))
  380.       (lcase v
  381.          ((initially finally)(parse-loop-initially v))
  382.          (nil nil)
  383.          (with      (parse-loop-with))
  384.          (declare   (parse-loop-declare (loop-pop) t))
  385.          (nodeclare  (setq *no-declare* (loop-pop)))
  386.          ;take argument to be consistent.
  387.          (increment (setq *loop-increment*
  388.                   (append (parse-loop-do) *loop-increment*)))
  389.          (end-test  (setq *loop-end-test*
  390.                   (append (parse-loop-do) *loop-end-test*)))
  391.          (with-unique (parse-loop-with nil t))
  392.          (:sloop-macro (parse-loop-macro v :sloop-macro))
  393.          (t
  394.            (cond (first
  395.                (setf found nil))
  396.              (t (loop-un-pop)))
  397.            (return 'done)))
  398.       (setf first nil))
  399.   found)
  400.  
  401. (defun parse-loop-with (&optional and-with only-if-not-there)
  402.   (let ((var  (loop-pop)))
  403.     (lcase (loop-peek)
  404.       (= (loop-pop)
  405.      (or (symbolp var) (error "Not a variable ~a" var))
  406.      (loop-add-binding var (loop-pop)
  407.                (not and-with) nil nil t only-if-not-there))
  408.       (t (loop-add-temps var nil nil (not and-with) only-if-not-there)))
  409.     (lcase (loop-peek)
  410.       (and (loop-pop)
  411.        (lcase (loop-pop)
  412.          (with (parse-loop-with t ))
  413.          (with-unique (parse-loop-with t t))
  414.          (t (loop-un-pop) (parse-loop-with t))
  415.          ))
  416.       (t nil))))
  417.  
  418. (defun parse-loop-do (&aux result)
  419.   (declare (special *loop-form*))
  420.   (do ((v (loop-pop) (loop-pop)) )
  421.       (())
  422.     (cond
  423.       ((listp v)
  424.        (push v result)
  425.        (or *loop-form* (return 'done)))
  426.       (t (loop-un-pop) (return 'done))))
  427.   (or result (error "empty clause"))
  428.   result)
  429.   
  430. (defun parse-loop-initially (command )
  431.   (declare (special *loop-prologue* *loop-epilogue* *loop-bindings*))
  432.   (lcase
  433.     command
  434.     (initially
  435.       (let ((form (parse-loop-do)))
  436.     (dolist (v (nreverse form))
  437.         (cond ((and (listp v)
  438.                 (member (car v) '(setf setq))
  439.                 (eql (length v) 3)
  440.                 (symbolp   (second v))
  441.                 (constantp (third v))
  442.                 (assoc (second v) (caar *loop-bindings*))
  443.                 (loop-add-binding (second v) (third v)
  444.                           nil nil nil t t)
  445.                 ))
  446.               (t (setf *loop-prologue*
  447.                    (cons v *loop-prologue*)))))))
  448.     (finally
  449.       (setf *loop-epilogue* (append (parse-loop-do) *loop-epilogue*)))))
  450.  
  451. (defun parse-one-when-clause ( &aux this-case  (want 'body) v)
  452.   (declare (special *loop-form*))
  453.   (prog
  454.     nil
  455.     next-loop
  456.     (and (null *loop-form*) (return 'done))
  457.     (setq v (loop-pop))
  458.     (lcase v
  459.        (:no-body)
  460.        (:collect (or (eql 'body want) (go finish))
  461.              (setq this-case (append  (parse-loop-collect) this-case))
  462.              (setq want 'and))
  463.        (when  (or (eql 'body want) (go finish))
  464.           (setq this-case (append   (parse-loop-when) this-case))
  465.           (setq want 'and))
  466.        (do    (or (eql 'body want) (go finish))
  467.           (setq this-case (append   (parse-loop-do) this-case))
  468.           (setq want 'and))
  469.        (and    (or (eql 'and  want) (error "Premature AND"))
  470.            (setq want 'body))
  471.        (t  (loop-un-pop)(return 'done)))
  472.     (go next-loop)
  473.     finish
  474.     (loop-un-pop))
  475.   (or this-case (error "Hanging conditional"))
  476.   this-case)
  477.  
  478.  
  479. (defun parse-loop-when (&aux initial else else-clause)
  480.   (declare (special *last-val* ))
  481.   (let ((test (cond ((l-equal *last-val* 'unless) `(not , (loop-pop)))
  482.             (t (loop-pop)))))
  483.     (setq initial (parse-one-when-clause))
  484.     (lcase (loop-peek)
  485.        (else
  486.          (loop-pop)
  487.          (setq else t)
  488.          (setq else-clause (parse-one-when-clause)))
  489.        (t nil))
  490.     `((cond (,test ,@ (nreverse initial))
  491.         ,@ (and else `((t ,@ (nreverse else-clause))))))))
  492.  
  493. (defun pointer-for-collect (collect-var)
  494.   (declare (special *loop-collect-pointers*))
  495.   (or (cdr (assoc collect-var *loop-collect-pointers*))
  496.       (let ((sym(loop-add-binding (gensym "POIN") nil nil :collect )))
  497.     (push (cons collect-var sym)
  498.           *loop-collect-pointers*)
  499.     sym)))
  500.  
  501. (defun parse-loop-collect ( &aux collect-var pointer name-val)
  502.   (declare (special *last-val* *loop-body* *loop-collect-var*
  503.             *loop-collect-pointers* *inner-sloop*
  504.             *loop-prologue* ))
  505.   (and *inner-sloop* (throw 'collect nil))
  506.   (let ((command   *last-val*)
  507.     (val (loop-pop)))
  508.     (lcase
  509.       (loop-pop)
  510.       (into (loop-add-binding (setq collect-var (loop-pop)) nil nil t nil t ))
  511.       (t (loop-un-pop)
  512.      (cond (*loop-collect-var* (setf collect-var *loop-collect-var*))
  513.            (t  (setf collect-var
  514.              (setf *loop-collect-var*
  515.                    (loop-add-binding (gensym "COLL") nil )))))))
  516.     (lcase command
  517.        ((append nconc collect)
  518.         (setf pointer (pointer-for-collect collect-var))
  519.         (cond (*use-locatives*
  520.             (pushnew `(setf ,pointer
  521.                     (locf ,collect-var))
  522.                  *loop-prologue* :test 'equal)))
  523.         (lcase command
  524.            ( append
  525.               (unless (and (listp val) (eql (car val) 'list))
  526.                   (setf val `(copy-list ,val))))
  527.            (t nil)))
  528.        (t nil))
  529.     (cond ((and  (listp val) (not *use-locatives*))
  530.        (setq name-val (loop-add-binding (gensym "VAL") nil nil)))
  531.       (t (setf name-val val)))
  532.     (let
  533.     ((result
  534.        (lcase
  535.          command
  536.          ((nconc append)
  537.           (let ((set-pointer
  538.               `(and (setf (cdr ,pointer) ,name-val)
  539.                 (setf ,pointer (last (cdr ,pointer))))))
  540.         (cond (*use-locatives*
  541.             (list set-pointer))
  542.               (t
  543.             `((cond (,pointer ,set-pointer)
  544.                 (t (setf ,pointer
  545.                      (last (setf
  546.                          ,collect-var
  547.                          ,name-val))))))))))
  548.          (collect
  549.            (cond (*use-locatives*
  550.                `((setf (cdr ,pointer)
  551.                    (setf ,pointer (cons ,name-val nil)))))
  552.              (t `((cond (,pointer
  553.                    (setf (cdr ,pointer)
  554.                      (setf ,pointer (cons ,name-val nil))))
  555.                 (t (setf ,collect-var
  556.                      (setf ,pointer
  557.                            (cons ,name-val nil)))))))))
  558.          (t (setq command (translate-name command))
  559.         (cond ((find command *additional-collections* :test 'l-equal)
  560.                (loop-parse-additional-collections
  561.              command collect-var name-val))
  562.               (t (error "loop fell off end ~a" command)))))))
  563.       (cond ((eql name-val val)
  564.          result)
  565.         (t (nconc result `((setf ,name-val ,val) )))))))
  566.  
  567. (defun loop-parse-additional-collections
  568.   (command collect-var name-val &aux eachtime)
  569.   (declare (special *loop-prologue* *last-val*
  570.             *loop-collect-var* *loop-epilogue* ))
  571.   (let* ((com  (find command *additional-collections* :test 'l-equal))
  572.      (helper (get com :sloop-collect)))
  573.     (let ((form (funcall helper collect-var name-val)))
  574.       (let ((*loop-form* form) *last-val*)
  575.     (declare (special  *loop-form* *last-val*))
  576.     (do ((v (loop-pop) (loop-pop)))
  577.         ((null *loop-form*))
  578.         (lcase v
  579.            (:no-body)
  580.            (do (setq eachtime (parse-loop-do)))))
  581.     eachtime))))
  582.  
  583. (defun the-type (symbol type)
  584.   (declare (special *no-declare*))
  585.   (and *no-declare* (setf type nil))
  586.   (and type (setf type (or (getf *Automatic-declarations* type)
  587.                (and  (not (keywordp type)) type))))
  588.   (and (consp type) (eq (car type) 'type) (setf type (second  type)))
  589.   (cond (type (list 'the type symbol ))
  590.     (t symbol)))
  591.  
  592. (defun type-error ()
  593.   (error "While checking a bound of a sloop, I found the wrong type 
  594. for something in sloop::*automatic-declarations*.
  595.     Perhaps your limit is wrong? 
  596. If not either use nodeclare t or set sloop::*automatic-declarations* to nil. 
  597. recompile."))
  598.  
  599.  
  600. ;;; this puts down code to check that automatic declarations induced by
  601. ;;; :from are indeed valid!  It checks both ends of the interval, and so
  602. ;;; need not check the numbers in between.
  603.  
  604. (defun make-value (value type-key &aux type )
  605.   (declare (special *no-declare* *type-test-limit*))
  606.   (cond ((and
  607.       (not *no-declare*)
  608.       *type-check*
  609.       (eq type-key :from)
  610.       (setq type (getf  *Automatic-declarations* type-key)))
  611.       (setq type
  612.            (cond ((and (consp type)
  613.                (eq (car type) 'type))
  614.               (second type))
  615.              (t type)))
  616.      (cond ((constantp value)
  617.         (let ((test-value
  618.                (cond (*type-test-limit*
  619.                   (eval (subst value
  620.                        'the-value *type-test-limit*)))
  621.                  (t (eval value)))))
  622.         (or (typep test-value type)
  623.             (error
  624.              "~&Sloop found the type of ~a was not type ~a,~%~
  625.                       Maybe you want to insert SLOOP NODECLARE T ..."
  626.              value
  627.              type))
  628.         (list value)))
  629.            (t  (let (chk)
  630.              `((let ,(cond ((atom value)
  631.                     nil)
  632.                    (t `((,(setq chk(gensym)) ,value))))
  633.              (or
  634.               (typep
  635.                ,(if *type-test-limit*
  636.                 (subst (or chk value)
  637.                        'the-value *type-test-limit*)
  638.                   (or chk value))
  639.                ',type)
  640.               (type-error))
  641.              ,(or chk value)))))))
  642.     (t (list value))))
  643.  
  644.  
  645. ;;; keep track of the bindings in a list *loop-bindings* each element of
  646. ;;; the list will give rise to a different let.  the car will be the
  647. ;;; variable bindings, the cdr the declarations.
  648.  
  649.  
  650. (defun loop-add-binding
  651.        (variable value &optional (new-level t) type force-type (force-new-value t)
  652.              only-if-not-there &aux tem)
  653. ;;; Add a variable binding to the current or new level.  If FORCE-TYPE,
  654. ;;; ignore a *no-declare*.  If ONLY-IF-NOT-THERE, check all levels.
  655.   (declare (special *loop-bindings*))
  656.   (when  (or new-level (null *loop-bindings*))
  657.      (push (cons nil nil) *loop-bindings*))
  658.   (cond ((setq tem (assoc variable (caar  *loop-bindings*) ))
  659.      (and force-new-value
  660.           (setf (cdr tem) (and value (make-value value type)))))
  661.     ((and (or only-if-not-there (and (null (symbol-package variable))
  662.                      (constantp value)))
  663.           (dolist (v (cdr *loop-bindings*))
  664.         (cond ((setq tem (assoc variable (car v)))
  665.                (and force-new-value
  666.                 (setf (cdr tem)
  667.                   (and value (make-value value type))))
  668.                (return t))))))
  669.     (t (push (cons variable  (and value (make-value value type)))
  670.          (caar *loop-bindings*))))
  671.   (and type (loop-declare-binding variable type force-type))
  672.   variable)
  673.  
  674. ;(defmacro nth-level (n) `(nth ,n *loop-bindings*))
  675. ;if x = (nth i *loop-bindings*)
  676. ;(defmacro binding-declares (x) `(cdr ,x)) ;(cons 'declare (binding-declares x)) to get honest declare statement
  677. ;(defmacro binding-values (x) `(car ,x))  ;(let (binding-values x) ) to get let.
  678.  
  679. (defun loop-declare-binding (var type force-type &optional odd-type
  680.                  &aux found )
  681.   (declare (special *loop-bindings* *automatic-declarations*
  682.             *no-declare* *loop-map*))
  683.   odd-type ;;ignored
  684.   (and type
  685.        (member type *auto-type*)
  686.        (setf type (getf  *automatic-declarations* type))
  687.        *auto-register*
  688.        (loop-declare-binding var :register force-type))
  689.   (when (and type(or force-type (null *no-declare*)))
  690.     (dolist (v *loop-bindings*)
  691.       (cond ((assoc var (car v)) (setf found t)
  692.          (pushnew
  693.            (if (and (consp type)
  694.             (eq (car type) 'type))
  695.            (list 'type (second type) var)
  696.            (if odd-type (list 'type type var)
  697.                
  698.            (list type var)))
  699.            (cdr v) :test 'equal)
  700.          (return 'done)
  701.          )))
  702.     (or found *loop-map* (error "Could not find variable ~a in bindings" var)))
  703.   var)
  704.  
  705. (defun parse-loop-declare (&optional (decl-list (loop-pop)) (force t))
  706.   (let ((type (car decl-list)) odd-type)
  707.     (cond ((eq type 'type)
  708.        (setf decl-list (cdr decl-list) type (car decl-list) odd-type t)))
  709.     (dolist (v (cdr decl-list))
  710.       (loop-declare-binding v (car decl-list) force odd-type))))
  711.     
  712. (defun loop-add-temps (form &optional val type new-level only-if-not-there)
  713.   (cond ((null form))
  714.     ((symbolp form)
  715.      (loop-add-binding form val new-level type nil  t only-if-not-there))
  716.     ((listp form)
  717.      (loop-add-temps (car form))
  718.      (loop-add-temps (cdr form)))))
  719.  
  720.  
  721. (defun add-from-data (data &rest args)
  722.    "rest = var begin end  incr direction or-eql"
  723.    (or data (setq data (copy-list '(nil 0 nil 1 + nil))))
  724.    (do ((l data (cdr l))
  725.         (v args (cdr v)))
  726.       ((null v) l)
  727.      (and (car v) (setf (car l) (car v))))
  728.    data)
  729.  
  730. (defun parse-loop-for ( &aux  inc  from-data)
  731.   (declare (special *loop-form*  *loop-map-declares*  *loop-map* 
  732.             *loop-body* *loop-increment* *no-declare*
  733.             *loop-prologue*
  734.             *loop-epilogue*
  735.             *loop-end-test*
  736.             *loop-bindings*
  737.             ))
  738.   (let* ((var (loop-pop)) test incr)
  739.     (do ((v (loop-pop) (loop-pop)))
  740.     (())
  741.     (lcase v
  742.            (in (let ((lis (gensym "LIS")))
  743.              (loop-add-temps var nil :in t)
  744.              (loop-add-binding lis (loop-pop) nil)
  745.              (push  `(desetq ,var (car ,lis)) *loop-body*)
  746.              (setf incr `(setf ,lis (cdr ,lis)))
  747.              (setq test   `(null ,lis) )
  748.              ))
  749.            (on (let ((lis
  750.                (cond ((symbolp var) var)
  751.                  (t (gensym "LIS")))))
  752.              (loop-add-temps var nil :in t)
  753.              (loop-add-binding lis (loop-pop) nil)
  754.              (setf incr `(setf ,lis (cdr ,lis)))
  755.              (unless (eql lis var)
  756.                  (push `(desetq ,var ,lis) *loop-body*))
  757.              (setf test `(null ,lis))))
  758.         
  759.            ((upfrom from)
  760.         (setq from-data (add-from-data from-data
  761.                            var (loop-pop) nil  nil '+)))
  762.            (downfrom
  763.          (setq from-data  (add-from-data
  764.                     from-data var (loop-pop) nil  nil '-)))
  765.            (by
  766.          (setq inc (loop-pop))
  767.          (cond (from-data
  768.              (setq from-data (add-from-data
  769.                        from-data nil nil nil inc)))
  770.                (t (assert (eq (car (third incr)) 'cdr))
  771.               (setq incr
  772.                 `(setf ,(second incr)
  773.                        ,(if (and (consp inc)
  774.                         (member (car inc) '(quote function)))
  775.                       `(,(second inc) ,(second incr))
  776.                       `(funcall
  777.                         ,inc ,(second incr))))))))
  778.            (below
  779.          (setq from-data (add-from-data from-data
  780.                         var nil (loop-pop) nil '+)))
  781.            (above
  782.          (setq from-data (add-from-data from-data
  783.                         var nil (loop-pop) nil '-)))
  784.            (to
  785.          (setq from-data (add-from-data from-data
  786.                         var nil (loop-pop) nil nil t)))
  787.            (:sloop-for (parse-loop-macro (translate-name v)
  788.                          :sloop-for var )
  789.                (return 'done))
  790.            (:sloop-map (parse-loop-map (translate-name v) var )
  791.                (return nil))
  792.            (t(or            
  793.            (loop-un-pop))
  794.          (return 'done))))
  795.     
  796.     ;;whew finished parsing a for clause..
  797.     
  798.     (cond (from-data
  799.         (let
  800.         ((op (nth 4 from-data))
  801.          (or-eql (nth 5 from-data))
  802.          (var (car from-data))
  803.          (end (third from-data))
  804.          (inc (fourth from-data))
  805.          type)
  806.           (loop-add-binding var (second from-data) t :from)
  807.           (or (constantp inc) (setq *no-declare* t))
  808.           (setf incr `(setf ,var ,(the-type `(,op  ,var ,inc) :from)))
  809.           (cond (end
  810.               (let ((lim (gensym "LIM"))
  811.                 (*type-test-limit*
  812.                   (cond ((and (eql inc 1)
  813.                       (null (nth 5 from-data)))
  814.                      nil)
  815.                     (t `(,op
  816.                        the-value , inc)))))
  817.             (declare (special *type-test-limit*))
  818.             (loop-add-binding lim end nil :from nil nil)
  819.             (setq test `(,(cond (or-eql
  820.                           (if (eq op '+) '> '<))
  821.                         (t (if (eq op '+) '>= '<=)))
  822.                      ,var ,lim))))
  823.             ((and (not *no-declare*)
  824.               *type-check*
  825.               (setq type (getf *automatic-declarations* :from))
  826.               (progn (if (and (consp type)(eq (car type) 'type))
  827.                      (setf type      (second type)))
  828.                  (subtypep type 'fixnum)))
  829.              (or (constantp inc) (error "increment must be constant."))
  830.              (push
  831.                `(or
  832.               ,(cond ((eq op '+)
  833.                   `(< ,var ,(- most-positive-fixnum
  834.                            (or inc 1))))
  835.                  (t `(> ,var  ,(+ most-negative-fixnum
  836.                           (or inc 1)))))
  837.               (type-error))
  838.                *loop-increment*)
  839.              )))))
  840.     
  841.     (and test (push (copy-tree `(and ,test (local-finish))) *loop-end-test*))
  842.     (and incr (push incr *loop-increment*))
  843.     ))
  844.  
  845.  
  846. (defun parse-loop-macro (v type &optional initial &aux result)
  847.   (declare (special *loop-form*))
  848.   (let ((helper (get v type)) args)
  849.     (setq args
  850.       (ecase type
  851.         (:sloop-for
  852.          (let ((tem (get v :sloop-for-args)))
  853.            (or (cdr tem) (error "sloop-for macro needs at least one arg"))
  854.            (cdr tem)))
  855.         (:sloop-macro(get v :sloop-macro-args))))
  856.     (let ((last-helper-apply-arg
  857.         (cond ((member '&rest args)
  858.            (prog1 *loop-form* (setf *loop-form* nil)))
  859.           (t (dotimes (i (length args) (nreverse result))
  860.                  (push (car *loop-form*) result)
  861.                  (setf *loop-form* (cdr *loop-form*)))))))
  862.       (setq *loop-form*
  863.         (append 
  864.           (case type
  865.             (:sloop-for (apply helper initial last-helper-apply-arg))
  866.             (:sloop-macro(apply helper  last-helper-apply-arg)))
  867.           *loop-form*)))))
  868.  
  869. (defun parse-loop-map (v var)
  870.   (declare (special *loop-map* *loop-map-declares* *loop-form*))
  871.   (and *loop-map* (error "Sorry only one allowed loop-map per sloop"))
  872.   (let ((helper (get v :sloop-map))
  873.     (args  (get v :sloop-map-args)))
  874.     (or args (error "map needs one arg before the key word"))
  875.     (cond ((member '&rest args)
  876.        (error "Build this in two steps if you want &rest")))
  877.     (let* (result
  878.         (last-helper-apply-arg
  879.           (dotimes (i (1- (length args)) (nreverse result))
  880.                (push (car *loop-form*) result)
  881.                (setf *loop-form* (cdr *loop-form*)))))
  882.       (setq *loop-map-declares*
  883.         (do ((v (loop-pop)(loop-pop)) (result))
  884.         ((null (l-equal v 'declare))
  885.          (loop-un-pop)
  886.          (and result (cons 'declare result)))
  887.         (push (loop-pop) result)))
  888.       (setq *loop-map* (apply helper var last-helper-apply-arg))
  889.       nil)))
  890.  
  891. (defun substitute-sloop-body (inner-body)
  892.   (declare (special *loop-map* *loop-map-declares*))
  893.     (cond (*loop-map*
  894.        (setf inner-body (list  (subst (cons 'progn inner-body)
  895.                       :sloop-body *loop-map*)))
  896.        (and *loop-map-declares*
  897.         (setf inner-body(subst *loop-map-declares*
  898.                        :sloop-map-declares inner-body)))))
  899.   inner-body)
  900.  
  901. ;;; **User Extensible Iteration Facility**
  902.  
  903. (eval-when (compile eval load)
  904. (defun def-loop-internal (name args  body type
  905.                    &optional list min-args max-args
  906.                    &aux (*print-case* :upcase)
  907.                    (helper (intern
  908.                   (format nil "~a-SLOOP-~a" name type))))
  909.   (and min-args (or (>= (length args) min-args)(error "need more args")))
  910.   (and max-args (or (<= (length args) max-args)(error "need less args")))
  911.   `(eval-when (load compile eval)
  912.           (defun ,helper ,args
  913.         ,@ body)
  914.           ,@ (and list `((pushnew ',name ,list)))
  915.           (setf (get ',name ,(intern (format nil "SLOOP-~a" type)
  916.                      (find-package 'keyword))) ',helper)
  917.           (setf (get ',name ,(intern (format nil "SLOOP-~a-ARGS" type)
  918.                      (find-package 'keyword))) ',args)))
  919. )
  920.         
  921.  
  922. ;;; DEF-LOOP-COLLECT lets you get a handle on the collection var.  exactly
  923. ;;; two args.  First arg=collection-variable. Second arg=value this time
  924. ;;; thru the loop.
  925.  
  926. (def-loop-collect sum (ans val)
  927.   `(initially (setq ,ans 0)
  928.     do (setq ,ans (+ ,ans ,val))))
  929. (def-loop-collect logxor (ans val)
  930.   `(initially (setf ,ans 0)
  931.   do (setf ,ans (logxor ,ans ,val))
  932.   declare (fixnum ,ans ,val)))
  933. (def-loop-collect maximize (ans val)
  934.   `(initially (setq ,ans nil) 
  935.   do (if ,ans (setf ,ans (max ,ans ,val)) (setf ,ans ,val))))
  936.  
  937. (def-loop-collect minimize (ans val) 
  938.   `(initially (setq ,ans nil)
  939.   do (if ,ans (setf ,ans (min ,ans ,val)) (setf ,ans ,val))))
  940.  
  941. (def-loop-collect count (ans val)
  942.   `(initially (setq ,ans 0)
  943.   do (and ,val (setf ,ans (1+ ,ans)))))
  944.  
  945. (def-loop-collect thereis (ans val)(declare(ignore ans))
  946.   `(do (if ,val (loop-return ,val))))
  947. (def-loop-collect always (ans val)
  948.   `(initially (setq ,ans t) do (and (null ,val)(loop-return nil))))
  949. (def-loop-collect never (ans val)
  950.   `(initially (setq ,ans t) do (and  ,val  (loop-return nil))))
  951.  
  952.  
  953. ;;; DEF-LOOP-MACRO
  954. ;;; If we have done
  955. ;;;  (def-loop-macro averaging (x)
  956. ;;;    `(sum ,x into .tot. and count t into .how-many.
  957. ;;;       finally (loop-return (/ .tot. (float .how-many.)))))
  958.  
  959. ;;; (def-loop-collect average (ans val)
  960. ;;;   `(initially (setf ,ans 0.0)
  961. ;;;     with-unique .how-many. = 0
  962. ;;;     do (setf ,ans (/  (+ (* .how-many. ,ans) ,val) (incf .how-many.)))
  963. ;;;     ))
  964.  
  965. ;;; Finally we show how to provide averaging with
  966. ;;; current value the acutal average.
  967.  
  968. (def-loop-macro averaging (x)
  969.   `(with-unique .average. = 0.0
  970.     and with-unique .n-to-average. = 0
  971.     declare (float .average. ) declare (fixnum .n-to-average.)
  972.     do (setf .average. (/
  973.              (+ (* .n-to-average. .average.) ,x)
  974.              (incf .n-to-average.)))
  975.     finally (loop-return .average.)))
  976.  
  977. (def-loop-macro repeat (x)
  978.   (let ((ind (gensym)))
  979.     `(for ,ind below ,x)))
  980.  
  981. (def-loop-macro return (x)
  982.   `(do (loop-return ,@ (if (and (consp x) (eq (car x) 'values))
  983.                (cdr x)
  984.              (list x)))))
  985.  
  986. ;;; then we can write:
  987. ;;; (sloop for x in l when (oddp x) averaging x)
  988.  
  989.  
  990. ;;; DEF-LOOP-FOR def-loop-for and def-loop-macro are almost identical
  991. ;;; except that the def-loop-for construct can only occur after a for:
  992.  
  993. ;;; (def-loop-for in-array (vars array)
  994. ;;;   (let ((elt (car vars))
  995. ;;;     (ind (second vars)))
  996. ;;;   `(for ,ind below (length ,array) do (setf ,elt (aref ,array ,ind)))))
  997.  
  998. ;;; (sloop for (elt ind) in-array ar when (oddp elt) collecting ind)
  999.  
  1000. ;;; You are just building something understandable by loop but minus the
  1001. ;;; for.  Since this is almost like a "macro", and users may want to
  1002. ;;; customize their own, the comparsion of tokens uses eq, ie. you must
  1003. ;;; import IN-ARRAY to your package if you define it in another one.
  1004. ;;; Actually we make a fancier in-array below which understands from, to,
  1005. ;;; below, downfrom,.. and can have either (elt ind) or elt as the
  1006. ;;; argument vars.
  1007.  
  1008. ;;; DEF-LOOP-MAP A rather general iteration construct which allows you to
  1009. ;;; map over things It can only occur after FOR.  There can only be one
  1010. ;;; loop-map for a given loop, so you want to only use them for
  1011. ;;; complicated iterations.
  1012.  
  1013. (def-loop-map in-table (var table)
  1014.   `(maphash #'(lambda ,var :sloop-map-declares :sloop-body) ,table))
  1015.  
  1016. ;;; Usage  (sloop for (key elt) in-table table
  1017. ;;;               declare (fixnum elt)
  1018. ;;;               when (oddp elt) collecting (cons key elt))
  1019.  
  1020.  
  1021. (def-loop-map in-package (var pkg)
  1022.   `(do-symbols (,var (find-package ,pkg))  :sloop-body))
  1023.  
  1024. ;;; Usage:
  1025. ;;; (defun te()
  1026. ;;;  (sloop for sym in-package 'sloop when (fboundp sym) count t)) 
  1027.  
  1028. ;;; IN-ARRAY that understands from,downfrowm,to, below, above,etc.  I used
  1029. ;;; a do for the macro iteration to be able include it here.
  1030.  
  1031. (def-loop-for in-array (vars array &rest args)
  1032.   (let (elt ind to)
  1033.     (cond ((listp vars) (setf elt (car vars) ind (second vars)))
  1034.       (t (setf elt vars ind (gensym "INDEX" ))))
  1035.     (let ((skip (do ((v args (cddr v)) (result))
  1036.             (())
  1037.            (lcase (car v)
  1038.                ((from downfrom) )
  1039.                ((to below above) (setf to t))
  1040.                (by)
  1041.                (t (setq args (copy-list v))
  1042.               (return (nreverse result))))
  1043.            (push (car v) result) (push (second v) result))))
  1044.       (or to (setf skip (nconc `(below (length ,array)) skip)))
  1045.       `(for ,ind 
  1046.     ,@ skip
  1047.     with ,elt 
  1048.     do (setf ,elt (aref ,array ,ind)) ,@ args))))
  1049.  
  1050. ;;; usage: IN-ARRAY
  1051. ;;; (sloop for (elt i) in-array ar from 4
  1052. ;;;       when (oddp i)
  1053. ;;;       collecting elt)
  1054.  
  1055. ;;; (sloop for elt in-array ar below 10 by 2
  1056. ;;;        do (print elt))
  1057.  
  1058. (def-loop-for = (var val)
  1059.   (lcase (loop-peek)
  1060.     (then (loop-pop) `(with ,var initially (desetq ,var ,val) increment (desetq ,var ,(loop-pop))))
  1061.     (t  `(with ,var do (desetq ,var ,val)))))
  1062.  
  1063. (def-loop-macro sloop (for-loop)
  1064.   (lcase (car for-loop)
  1065.     (for))
  1066.   (let (*inner-sloop* *loop-body* *loop-map* inner-body
  1067.     (finish-loop (gensym "FINISH"))
  1068.     a b c e f (*loop-form* for-loop))
  1069.     (declare (special *inner-sloop* *loop-end-test* *loop-increment*
  1070.               *product-for* *loop-map*
  1071.               *loop-form*  *loop-body*  *loop-prologue*
  1072.               *loop-epilogue* *loop-end-test*
  1073.               *loop-bindings*
  1074.               ))
  1075.     (setf *product-for* t)
  1076.     (loop-pop)
  1077.     (sloop-swap)
  1078.     (parse-loop-for)
  1079.      (sloop-swap)
  1080.     (do ()
  1081.     ((null *loop-form*))
  1082.       (cond ((catch 'collect  (parse-loop1)))
  1083.         ((null *loop-form*)(return 'done))
  1084.         (t ;(fsignal "hi")
  1085.          (print *loop-form*)
  1086.          (sloop-swap)
  1087.          (parse-loop-collect)
  1088.          (sloop-swap)
  1089.                   (print *loop-form*)
  1090.          )))
  1091.     (sloop-swap)
  1092.     (setf inner-body (nreverse *loop-body*))
  1093.     (and *loop-map*  (setf inner-body (substitute-sloop-body inner-body)))
  1094.     (let ((bod
  1095.         `(macrolet ((local-finish () `(go ,',finish-loop)))
  1096.           (tagbody
  1097.           ,@ (nreverse *loop-prologue*)
  1098.               ,@ (and (null *loop-map*) '(next-loop))
  1099.           ,@ (nreverse *loop-end-test*)
  1100.           ,@ inner-body
  1101.           ,@ (nreverse *loop-increment*)
  1102.           ,@ (and (null *loop-map*) '((go next-loop)))
  1103.           ,finish-loop
  1104.           ,@ (nreverse *loop-epilogue*)))))
  1105.       (dolist (v *loop-bindings*)
  1106.     (setf bod
  1107.           `(let ,(loop-let-bindings v) ,@(and (cdr v) `(,(cons 'declare (cdr v))))
  1108.             ,bod)))
  1109.       (sloop-swap)
  1110.       `(do ,bod))))
  1111.  
  1112. ;;; Usage: SLOOP (FOR 
  1113. ;;; (defun te ()
  1114. ;;;   (sloop for i below 5
  1115. ;;;      sloop (for j  to i collecting (list i j))))
  1116.  
  1117. (def-loop-for in-carefully (var lis)
  1118.   "Path with var in lis except lis may end with a non nil cdr" 
  1119.   (let ((point (gensym "POINT")))
  1120.     `(with ,point and with ,var initially (setf ,point ,lis)
  1121.            do(desetq ,var (car ,point))
  1122.        end-test (and (atom ,point)(local-finish))
  1123.        increment (setf ,point (cdr ,point)))))
  1124.  
  1125. ;;; Usage: IN-CAREFULLY
  1126. ;;; (defun te (l)
  1127. ;;;   (sloop for v in-carefully l collecting v))
  1128.  
  1129. ;;; Note the following is much like the mit for i first expr1 then expr2
  1130. ;;; but it is not identical, in that if expr1 refers to paralell for loop
  1131. ;;; it will not get the correct initialization.  But since we have such
  1132. ;;; generality in the our definition of a for construct, it is unlikely
  1133. ;;; that all people who define This is why we use a different name
  1134.  
  1135. (def-loop-for first-use (var expr1 then expr2)
  1136.   (or (l-equal then 'then) (error "First must be followed by then"))
  1137.   `(with ,var initially (desetq ,var ,expr1) increment (desetq ,var ,expr2)))
  1138.  
  1139. ;;; I believe the following is what the original loop does with the FIRST
  1140. ;;; THEN construction.  
  1141.  
  1142. (def-loop-for first (var expr1 then expr2)
  1143.   (declare (special *loop-increment*))
  1144.   (or (l-equal then 'then) (error "First must be followed by then"))
  1145.   ;; If this is the first for, then we don't need the flag, but can
  1146.   ;; move the FIRST setting into the INITIALLY section
  1147.   (cond ((null *loop-increment*)
  1148.      `(with ,var initially (desetq ,var ,expr1)
  1149.         increment (desetq ,var ,expr2)))
  1150.     (t
  1151.       (let ((flag (gensym)))
  1152.         `(with ,var with ,flag
  1153.            do (cond (,flag (desetq ,var ,expr2))
  1154.                 (t (desetq ,var ,expr1)))
  1155.            increment (desetq ,flag t))))))
  1156.  
  1157.  
  1158. (defvar *collate-order* #'<)
  1159.  
  1160. ;;; of course this should be a search of the list based on the order and
  1161. ;;; splitting into halves (binary search).  I was too lazy to include one
  1162. ;;; here, but it should be done.
  1163.  
  1164. (defun find-in-ordered-list
  1165.        (it list &optional (order-function *collate-order*) &aux prev)
  1166.   (do ((v list (cdr v)))
  1167.       ((null v) (values prev nil))
  1168.      (cond ((eql (car v) it) (return (values v t)))
  1169.            ((funcall order-function it (car v))
  1170.         (return (values prev nil))))
  1171.      (setq prev v)))
  1172.  
  1173. (def-loop-collect collate (ans val)
  1174.   "Collects values into a sorted list without duplicates.
  1175. Order based order function *collate-order*"
  1176.   `(do (multiple-value-bind
  1177.        (after already-there )
  1178.        (find-in-ordered-list ,val ,ans)
  1179.        (unless already-there
  1180.       (cond (after (setf (cdr after) (cons ,val (cdr after))))
  1181.         (t (setf ,ans (cons ,val ,ans))))))))
  1182.  
  1183. ;;; Usage: COLLATE
  1184. ;;; (defun te ()
  1185. ;;;   (let ((res
  1186. ;;;       (sloop for i below 10
  1187. ;;;               sloop (for j downfrom 8 to 0 
  1188. ;;;                  collate (* i (mod j (max i 1)) (random 2)))))
  1189. ;;;
  1190.  
  1191. ;;;  Two implementations of slooping over the fringe of a tree
  1192.  
  1193. ;;;(defun map-fringe (fun tree)
  1194. ;;;      (do ((v tree))
  1195. ;;;           (())
  1196. ;;;    (cond ((atom v)
  1197. ;;;            (and v (funcall fun v))(return 'done))
  1198. ;;;          ((atom (car v))
  1199. ;;;            (funcall fun (car v)))
  1200. ;;;          (t (map-fringe fun (car v) )))
  1201. ;;;         (setf v (cdr v))))
  1202. ;;;
  1203. ;;;(def-loop-map in-fringe (var tree)
  1204. ;;;  "Map over the non nil atoms in the fringe of tree"
  1205. ;;;  `(map-fringe #'(lambda (,var) :sloop-map-declares :sloop-body) ,tree))
  1206.  
  1207. ;;; The next version is equivalent to the previous but uses labels and so
  1208. ;;; avoids having to funcall an anonymous function. [as suggested
  1209. ;;; by M. Ballantyne]
  1210.  
  1211. (def-loop-map in-fringe (var tree)
  1212.   "Map over the non nil atoms in the fringe of tree"
  1213.   (let  ((v (gensym)))
  1214.     `(let (,var)
  1215.        (labels
  1216.        ((map-fringe-aux (.xtree.)
  1217.                 (do ((,v .xtree.))
  1218.                 ((null ,v))
  1219.                   (cond ((atom ,v) (setf ,var ,v) (setf ,v nil))
  1220.                     (t (setf ,var (car ,v))(setf ,v (cdr ,v))))
  1221.                   (cond ((null ,var))
  1222.                     ((atom ,var)
  1223.                      :sloop-map-declares :sloop-body)
  1224.                     (t (map-fringe-aux ,var ))))))
  1225.      (map-fringe-aux ,tree)))))
  1226.  
  1227. ;;; Usage: IN-FRINGE
  1228. ;;; (sloop for v in-fringe '(1 2 (3 (4 5) . 6) 8 1 2)
  1229. ;;;        declare (fixnum v)
  1230. ;;;        maximize v)
  1231.